import { isUndefined, isNull, emtpyToUndefined, toString } from "mmb";
import * as activity_user_procedurepb from "../grpc-client/service/activity_user_procedure_pb";
import * as sharedpb from "../grpc-client/shared/message_pb";
import {
  getBgsActivityUserProcedureOpSafely,
  getMetadata,
  getOptionsOfLight,
  wrapperGrpcError,
} from "../grpc-client/grpcAdapter";
import {
  AwardInfo,
  DoCheckIn1Param,
  DoLottery1Param,
  DoLottery1Ret,
  GetCheckIn1Ret,
  Prize,
  CheckIn1Def,
  CheckIn1Procedure,
  CheckIn1Stat,
  ActivityNeedTypeInfo,
  Lottery1Procedure,
  GetLottery1Ret,
} from "./declareTypes";
import AwardType from "../bg-enums/awardType";
import ActivityType from "../bg-enums/activityType";
import ActivityProcessStatus from "../bg-enums/activityProcessStatus";
import {
  pbTimestampToJs,
  checkIn1PbToObject,
  checkIn1ObjectToPb,
  lottery1PbToObject,
  lottery1ObjectToPb,
} from "./helper";
/****************************************************************************************/
/*                                   activity_user_procedure entity                     */
/****************************************************************************************/

const awardInfoPbToObject = (pb: sharedpb.AwardInfo): AwardInfo => {
  // console.log("pb.getSkusList=>", pb.getSkusList());

  return {
    type: pb.getType() as AwardType,
    desc: pb.getDesc(),
    prize: pb.getPrize() > 0 ? pb.getPrize() : undefined,
  };
};

const prizePbToObject = (pb: activity_user_procedurepb.PrizeEntity): Prize => {
  // console.log("pb.getSkusList=>", pb.getSkusList());
  return {
    productId: toString(pb.getProductId()),
    productName: pb.getProductName(),
    productPics: pb.getProductPicsList(),
    quantity: pb.getQuantity(),
  };
};

const checkIn1DefPbToObject = (
  pb: activity_user_procedurepb.CheckIn1DefEntity
): CheckIn1Def => {
  return {
    activityId: toString(pb.getActivityId()),
    brandId: toString(pb.getBrandId()),
    name: pb.getName(),
    type: pb.getType() as ActivityType,
    intro: JSON.parse(pb.getIntro()),
    background: pb.getBackground(),
    poster: emtpyToUndefined(pb.getPoster()),
    tel: pb.getTel(),
    brandName: pb.getBrandName(),
    brandPic: pb.getBrandPic(),
    prizes: pb.getPrizesList().map(prizePbToObject),
    typeInfo: checkIn1PbToObject(pb.getTypeInfo()!),
    isAvailable: pb.getIsAvailable(),
  };
};

const checkIn1ProcedurePbToObject = (
  pb: activity_user_procedurepb.CheckIn1ProcedureEntity
): CheckIn1Procedure => {
  return {
    isCheckInToday: pb.getIsCheckInToday(),
    isContinuous: pb.getIsContinuous(),
    continuousCheckInCount: pb.getContinuousCheckInCount(),
    bCoins: pb.getBCoins(),
  };
};

const checkIn1StatPbToObject = (
  pb: activity_user_procedurepb.CheckIn1StatEntity
): CheckIn1Stat => {
  return {
    latestAccessed: pbTimestampToJs(pb.getLatestAccessed()),
    pv: pb.getPv(),
    uv: pb.getUv(),
    iv: pb.getIv(),
  };
};

const activityNeedTypeInfoPbToObject = (
  pb: activity_user_procedurepb.ActivityNeedTypeInfoEntity
): ActivityNeedTypeInfo => {
  return {
    activityId: toString(pb.getActivityId()),
    brandId: toString(pb.getBrandId()),
    name: pb.getName(),
    type: pb.getType() as ActivityType,
    intro: JSON.parse(pb.getIntro()),
    processStatus: pb.getProcessStatus() as ActivityProcessStatus,
    published: pbTimestampToJs(pb.getPublished()),
    begined: pbTimestampToJs(pb.getBegined())!,
    ended: pbTimestampToJs(pb.getEnded())!,
    timeRanges: pb.getTimeRangesList().map((v) => ({
      beginAt: v.getBeginAt(),
      endAt: v.getEndAt(),
    })),
    background: pb.getBackground(),
    poster: emtpyToUndefined(pb.getPoster()),
    tel: pb.getTel(),
    brandName: pb.getBrandName(),
    brandPic: pb.getBrandPic(),
    prizes: pb.getPrizesList().map(prizePbToObject),
    typeInfo: lottery1PbToObject(pb.getLottery1()!),
  };
};

const lottery1ProcedurePbToObject = (
  pb: activity_user_procedurepb.Lottery1ProcedureEntity
): Lottery1Procedure => {
  return {
    availableCount: pb.getAvailableCount(),
    drawedCount: pb.getDrawedCount(),
  };
};

/****************************************************************************************/
/*                                   activity_user_procedure cmd                        */
/****************************************************************************************/

export const doCheckIn1 = async ({
  activityId,
  userId,
  userOpenId,
  authorizeNextRemind,
}: DoCheckIn1Param): Promise<AwardInfo[]> => {
  const cl = getBgsActivityUserProcedureOpSafely();
  const req = new activity_user_procedurepb.DoCheckIn1Request();

  req.setActivityId(Number(activityId));
  req.setUserId(Number(userId));
  req.setUserOpenId(userOpenId);
  req.setAuthorizeNextRemind(authorizeNextRemind);

  return new Promise((resolve, reject) => {
    cl.doCheckIn1(req, getMetadata(), getOptionsOfLight(), (err, res) => {
      if (!isNull(err)) {
        reject(wrapperGrpcError(err.details));
        return;
      }
      const opRet = res.getOpRet()!;
      if (!opRet.getSuccess()) {
        reject(wrapperGrpcError(opRet.getMsg()));
        return;
      }
      resolve(res.getAwardInfosList().map(awardInfoPbToObject));
    });
  });
};

export const doLottery1 = async ({
  activityId,
  userId,
  userOpenId,
}: DoLottery1Param): Promise<DoLottery1Ret> => {
  const cl = getBgsActivityUserProcedureOpSafely();
  const req = new activity_user_procedurepb.DoLottery1Request();

  req.setActivityId(Number(activityId));
  req.setUserId(Number(userId));
  req.setUserOpenId(userOpenId);

  return new Promise((resolve, reject) => {
    cl.doLottery1(req, getMetadata(), getOptionsOfLight(), (err, res) => {
      if (!isNull(err)) {
        reject(wrapperGrpcError(err.details));
        return;
      }
      const opRet = res.getOpRet()!;
      if (!opRet.getSuccess()) {
        reject(wrapperGrpcError(opRet.getMsg()));
        return;
      }
      const ret: DoLottery1Ret = {
        awardInfos: res.getAwardInfosList().map(awardInfoPbToObject),
        procedure: lottery1ProcedurePbToObject(res.getProcedure()!),
      };
      resolve(ret);
    });
  });
};

/****************************************************************************************/
/*                                   activity_user_procedure query                      */
/****************************************************************************************/

export const getCheckIn1 = async (
  brandId: string,
  userId: string
): Promise<GetCheckIn1Ret> => {
  const cl = getBgsActivityUserProcedureOpSafely();
  const req = new activity_user_procedurepb.GetCheckIn1Request();

  req.setBrandId(Number(brandId));
  req.setUserId(Number(userId));

  return new Promise((resolve, reject) => {
    cl.getCheckIn1(req, getMetadata(), getOptionsOfLight(), (err, res) => {
      if (!isNull(err)) {
        reject(wrapperGrpcError(err.details));
        return;
      }
      const opRet = res.getOpRet()!;
      if (!opRet.getSuccess()) {
        reject(wrapperGrpcError(opRet.getMsg()));
        return;
      }
      resolve({
        def: checkIn1DefPbToObject(res.getDef()!),
        procedure: checkIn1ProcedurePbToObject(res.getProcedure()!),
        stat: checkIn1StatPbToObject(res.getStat()!),
      });
    });
  });
};

export const getLottery1 = async (
  activityId: string,
  userId: string
): Promise<GetLottery1Ret> => {
  const cl = getBgsActivityUserProcedureOpSafely();
  const req = new activity_user_procedurepb.GetLottery1Request();

  req.setActivityId(Number(activityId));
  req.setUserId(Number(userId));

  return new Promise((resolve, reject) => {
    cl.getLottery1(req, getMetadata(), getOptionsOfLight(), (err, res) => {
      if (!isNull(err)) {
        reject(wrapperGrpcError(err.details));
        return;
      }
      const opRet = res.getOpRet()!;
      if (!opRet.getSuccess()) {
        reject(wrapperGrpcError(opRet.getMsg()));
        return;
      }
      resolve({
        def: activityNeedTypeInfoPbToObject(res.getDef()!),
        procedure: lottery1ProcedurePbToObject(res.getProcedure()!),
      });
    });
  });
};
